package com.itheima.consumer.mq;

import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
@Slf4j
public class SpringRabbitListener {

    //设置监听的队列
    @RabbitListener(queues = "simple.queue")
    public void ListenSimpleQueue(Message message) {//会自动转换监听到的格式为String
        log.info("接收到的消息message:{}", new String(message.getBody()));
        log.info("接收到的消息messageId:{}", message.getMessageProperties().getMessageId());
        throw new RuntimeException("我是故意的!");
    }

    //设置监听的队列
    @RabbitListener(queues = "work.queue")
    public void ListenWorkQueue1(String message) throws InterruptedException {//会自动转换监听到的格式为String
        System.out.println("接收者1接收到message:" + message);
        Thread.sleep(25);
    }

    //设置监听的队列
    @RabbitListener(queues = "work.queue")
    public void ListenWorkQueue2(String message) throws InterruptedException {//会自动转换监听到的格式为String
        System.out.println("接收者2接收到message:" + message);
        Thread.sleep(200);
    }

    //设置监听的队列
    @RabbitListener(queues = "fanout.queue1")
    public void ListenFanoutQueue1(String message) {//会自动转换监听到的格式为String
        System.out.println("消费者1接收到message:" + message);
    }


    //设置监听的队列
    @RabbitListener(queues = "fanout.queue2")//广播模式的路由器
    public void ListenFanoutQueue2(String message) {//会自动转换监听到的格式为String
        System.out.println("消费者2接收到message:" + message);
    }

    //设置监听的队列
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "direct.queue1", declare = "true"),//指定队列名称,declare指定持久化,默认为true(要持久化)
            exchange = @Exchange(name = "hmall.direct", type = ExchangeTypes.DIRECT),//指定交换机名称,也是默认持久化  type 指定交换机类型
            key = {"red", "blue"}//指定RoutingKey 可以填多个
    ))
    //广播模式的路由器
    public void ListenDirectQueue1(String message) {//会自动转换监听到的格式为String
        System.out.println("消费者1接收到message:" + message);
    }


    //设置监听的队列
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "direct.queue2", durable = "true"),//指定队列名称,declare指定持久化,默认为true(要持久化)
            exchange = @Exchange(name = "hmall.direct", type = ExchangeTypes.DIRECT),//指定交换机名称
            key = {"red", "yellow"}//指定RoutingKey 可以填多个
    ))
    //广播模式的路由器
    public void ListenDirectQueue2(String message) {//会自动转换监听到的格式为String
        System.out.println("消费者2接收到message:" + message);
    }


    //设置监听的队列
    @RabbitListener(queues = "topic.queue1")//广播模式的路由器
    public void ListenTopicQueue1(String message) {//会自动转换监听到的格式为String
        System.out.println("消费者1接收到message:" + message);
    }


    //设置监听的队列
    @RabbitListener(queues = "topic.queue2")//广播模式的路由器
    public void ListenTopicQueue2(String message) {//会自动转换监听到的格式为String
        System.out.println("消费者2接收到message:" + message);
    }


    //设置监听的队列
    @RabbitListener(queues = "object.queue")//广播模式的路由器
    public void ListenObjectQueue1(Map<String, Object> message) {//会自动转换监听到的格式为String
        System.out.println("消费者1接收到message:" + message);
    }


    /**
     * 死信流程
     * publisher -> exchange -> queue -> dlx.direct -> dlx.queue -> consumer
     * publisher发送消息设置过期时间,到达exchange后,由于没有消费者 consumer,这条消息会在queue里面等待
     * 等到queue中的这条消息超时,会被列为死信,进入dlx.direct,然后进入dlx.queue,会进入consumer
     * <p>
     * 因为死信交换机和死信队列要有消费者consumer,而普通交换机和普通队列没有消费者,所以死信部分可以直接用注解定义(注解定义会直接绑定消费者)
     * 而普通交换机和普通队列部分要单独定义(这里使用bean定义,在Normalconfiguration中)
     *
     * @param message
     */
    //设置死信
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "dlx.queue"),
            exchange = @Exchange(name = "dlx.direct", type = ExchangeTypes.DIRECT),
            key = {"hi"}
    ))//广播模式的路由器
    public void ListenDlxQueue(String message) {//会自动转换监听到的格式为String
        log.info("消费者接收到dlx.queue的信息:【{}】", message);
    }

    /**
     * 基于插件的延迟队列,此插件可以自动把交换机设置为死信交换机,并且把队列设置为死信队列
     * 只需定义交换机的时候,设置delayed = "true"即可
     *
     * @param message
     */
    //已设置插件,设置死信
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "delay.queue", durable = "true"),
            exchange = @Exchange(name = "delay.direct", delayed = "true"),
            key = {"hi"}
    ))//广播模式的路由器
    public void ListenDelayQueue(String message) {//会自动转换监听到的格式为String
        log.info("消费者接收到delay.queue的信息:【{}】", message);
    }


}
